Spring MVC防止数据重复提交 - - ITeye博客

创建时间:2019/8/28 15:17
来源:https://www.iteye.com/blog/ljz0721cx-2181581


来讲一下如何在Spring MVC里面解决此问题(其它框架也一样,逻辑一样,思想一样,和具体框架没什么关系)。要解决重复提交,有很多办法,比如说在提交完成后redirect一下,也可以用本文提到的使用token的方法(我不使用redirect是因为那样解决不了ajax提交数据或者移动应用提交数据,另一个原因是现在比较通行的方法是使用token,像python里的django框架也是使用token来解决)。
使用token的逻辑是,给所有的url加一个拦截器,在拦截器里面用java的UUID生成一个随机的UUID并把这个UUID放到session里面,然后在浏览器做数据提交的时候将此UUID提交到服务器。服务器在接收到此UUID后,检查一下该UUID是否已经被提交,如果已经被提交,则不让逻辑继续执行下去…
注解Token代码:
Java代码
 收藏代码
  1. @Target(ElementType.METHOD)  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. public @interface Token {  
  4.    
  5.     boolean save() default false;  
  6.    
  7.     boolean remove() default false;  
  8. }  
  9. 拦截器TokenInterceptor代码:  
  10. public class TokenInterceptor extends HandlerInterceptorAdapter {  
  11.    
  12.     @Override  
  13.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
  14.         if (handler instanceof HandlerMethod) {  
  15.             HandlerMethod handlerMethod = (HandlerMethod) handler;  
  16.             Method method = handlerMethod.getMethod();  
  17.             Token annotation = method.getAnnotation(Token.class);  
  18.             if (annotation != null) {  
  19.                 boolean needSaveSession = annotation.save();  
  20.                 if (needSaveSession) {  
  21.                     request.getSession(false).setAttribute("token", UUID.randomUUID().toString());  
  22.                 }  
  23.                 boolean needRemoveSession = annotation.remove();  
  24.                 if (needRemoveSession) {  
  25.                     if (isRepeatSubmit(request)) {  
  26.                         return false;  
  27.                     }  
  28.                     request.getSession(false).removeAttribute("token");  
  29.                 }  
  30.             }  
  31.             return true;  
  32.         } else {  
  33.             return super.preHandle(request, response, handler);  
  34.         }  
  35.     }  
  36.    
  37.     private boolean isRepeatSubmit(HttpServletRequest request) {  
  38.         String serverToken = (String) request.getSession(false).getAttribute("token");  
  39.         if (serverToken == null) {  
  40.             return true;  
  41.         }  
  42.         String clinetToken = request.getParameter("token");  
  43.         if (clinetToken == null) {  
  44.             return true;  
  45.         }  
  46.         if (!serverToken.equals(clinetToken)) {  
  47.             return true;  
  48.         }  
  49.         return false;  
  50.     }  
  51. }  

相应的sping容器的额配置文件自己加上
相关代码已经注释,相信你能看懂。
关于这个方法的用法是:在需要生成token的controller上增加@Token(save=true),而在需要检查重复提交的controller上添加@Token(remove=true)就可以了。
另外,你需要在view里在form里增加下面代码:
<input type="hidden" name="token" value="${token}" />
已经完成了,去试试看你的数据还能重复提交了吧。
评论